import { type Mark, Node } from "@rivet/model";
import { Step, StepResult } from "./step.ts";
import type { Draft } from "immer";

export class AddMarkStep extends Step {
  id: string;
  mark: Mark;
  constructor(
    id: string,
    mark: Mark,
  ) {
    super();
    this.id = id;
    this.mark = mark;
  }
  apply(draft: Draft<Node> | null, doc: Node): StepResult | undefined {
    const node = doc.nodeAt(this.id);
    if (!node) return StepResult.fail("id 对应的节点不存在");
    if (draft) {
      Node.addMark(draft, this.id, this.mark);
      return;
    }
    return StepResult.fromReplace(doc, (draftState) => {
      Node.addMark(draftState, this.id, this.mark);
    }, (patches, inversePatches) => {
      this.changes.push(...patches);
      this.inverse.push(...inversePatches);
    });
  }
}

Step.jsonID("addMark", AddMarkStep);

export class RemoveMarkStep extends Step {
  id: string;
  filter: (mark: Mark) => boolean;
  constructor(
    id: string,
    filter: (mark: Mark) => boolean,
  ) {
    super();
    this.id = id;

    this.filter = filter;
  }

  apply(draft: Draft<Node> | null, doc: Node): StepResult | undefined {
    const node = doc.nodeAt(this.id);
    if (!node) return StepResult.fail("id 对应的节点不存在");
    if (draft) {
      Node.removeMark(draft, this.id, this.filter);
      return;
    }
    return StepResult.fromReplace(doc, (draftState) => {
      Node.removeMark(draftState, this.id, this.filter);
    }, (patches, inversePatches) => {
      this.changes.push(...patches);
      this.inverse.push(...inversePatches);
    });
  }
}

Step.jsonID("removeMark", RemoveMarkStep);
